package live.zs.securitytokenstarter.config;

import live.zs.securitytokenstarter.exception.AccessException;
import live.zs.securitytokenstarter.security.JwtTokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * @author madison
 * @description
 * @date 2021/7/16 23:08
 */
@Component
public class CustomAuthManager {

    public static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String ACCESS_TOKEN = "accessToken";
    private static final String PARAM_USERNAME = "username";
    private static final String PARAM_PASSWORD = "password";

    @Autowired
    private JwtTokenManager tokenManager;
    @Autowired
    private AuthenticationManager authenticationManager;

    public String login(HttpServletRequest request) {
        String token = resolveToken(request);
        if (!StringUtils.hasText(token)) {
            throw new AccessException("user not found!");
        }

        tokenManager.validateToken(token);
        Authentication authentication = tokenManager.getAuthentication(token);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return token;
    }

    /**
     * Get token from header.
     */
    private String resolveToken(HttpServletRequest request){
        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
            return bearerToken.substring(7);
        }
        bearerToken = request.getParameter(ACCESS_TOKEN);
        if (!StringUtils.hasText(bearerToken)) {
            String userName = request.getParameter(PARAM_USERNAME);
            String password = request.getParameter(PARAM_PASSWORD);
            bearerToken = resolveTokenFromUser(userName, password);
        }
        return bearerToken;
    }

    private String resolveTokenFromUser(String userName, String rawPassword){
        String finalName;
        Authentication authenticate;
        try {
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            userName, rawPassword);
            // zs zs123
            authenticate = authenticationManager.authenticate(authenticationToken);
        } catch (AuthenticationException e) {
            throw new AccessException("username or password is not correct!");
        }

        if (null == authenticate || !StringUtils.hasText(authenticate.getName())) {
            finalName = userName;
        } else {
            finalName = authenticate.getName();
        }

        return tokenManager.createToken(finalName);
    }
}
